home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Graphics / SPD / Sources / libply.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-27  |  38.0 KB  |  1,304 lines  |  [TEXT/R*ch]

  1. /*
  2.  * libply.c - a library of polygonized object output routines.
  3.  *
  4.  * Author:  Alexander Enzmann
  5.  *
  6.  */
  7.  
  8.  
  9. /*-----------------------------------------------------------------*/
  10. /* include section */
  11.  
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <math.h>
  15. #include <string.h>
  16. #include "lib.h"
  17. #include "drv.h"
  18.  
  19.  
  20. /*-----------------------------------------------------------------*/
  21. /* defines/constants section */
  22.  
  23. #define VERT(i, a) ((verts[gPoly_vbuffer[i]])[a])
  24.  
  25.  
  26. /*-----------------------------------------------------------------*/
  27. /* Polygon stack for making PLG files */
  28. object_ptr gPolygon_stack = NULL;
  29.  
  30. /* Keep track of how many vertices/faces have been emitted */
  31. unsigned long gVertex_count = 0; /* Vertex coordinates */
  32. unsigned long gNormal_count = 0; /* Vertex normals */
  33. unsigned long gFace_count = 0;
  34.  
  35. /* Storage for polygon indices */
  36. unsigned int *gPoly_vbuffer = NULL;
  37. int *gPoly_end = NULL;
  38.  
  39. /* Globals to determine which axes can be used to split the polygon */
  40. int gPoly_Axis1 = 0;
  41. int gPoly_Axis2 = 1;
  42.  
  43.  
  44. /*-----------------------------------------------------------------*/
  45. void
  46. lib_output_polygon_cylcone(base_pt, apex_pt)
  47.     COORD4 base_pt, apex_pt;
  48. {
  49.     double angle, delta_angle, divisor;
  50.     COORD3 axis, dir, norm_axis, start_norm;
  51.     COORD3 norm[4], vert[4], start_radius[4];
  52.     MATRIX mx;
  53.     int    i;
  54.  
  55.     SUB3_COORD3(axis, apex_pt, base_pt);
  56.     COPY_COORD3(norm_axis, axis);
  57.     lib_normalize_vector(norm_axis);
  58.  
  59.     SET_COORD3(dir, 0.0, 0.0, 1.0);
  60.     CROSS(start_norm, axis, dir);
  61.     divisor = lib_normalize_vector(start_norm);
  62.  
  63.     if (ABSOLUTE(divisor) < EPSILON2) {
  64.     SET_COORD3(dir, 1.0, 0.0, 0.0);
  65.     CROSS(start_norm, axis, dir);
  66.     lib_normalize_vector(start_norm);
  67.     }
  68.  
  69.     start_radius[0][X] = start_norm[X] * base_pt[W];
  70.     start_radius[0][Y] = start_norm[Y] * base_pt[W];
  71.     start_radius[0][Z] = start_norm[Z] * base_pt[W];
  72.     ADD3_COORD3(vert[0], base_pt, start_radius[0]);
  73.  
  74.     start_radius[1][X] = start_norm[X] * apex_pt[W];
  75.     start_radius[1][Y] = start_norm[Y] * apex_pt[W];
  76.     start_radius[1][Z] = start_norm[Z] * apex_pt[W];
  77.     ADD3_COORD3(vert[1], apex_pt, start_radius[1]);
  78.  
  79.     COPY_COORD3(norm[0], start_norm);
  80.     COPY_COORD3(norm[1], start_norm);
  81.  
  82.     delta_angle = 2.0 * PI / (double)(2*gU_resolution);
  83.     for (i=1,angle=delta_angle;i<=2*gU_resolution;++i,angle+=delta_angle) {
  84.     lib_create_axis_rotate_matrix(mx, norm_axis, angle);
  85.     lib_transform_vector(vert[2], start_radius[1], mx);
  86.     ADD2_COORD3(vert[2], apex_pt);
  87.     lib_transform_vector(norm[2], start_norm, mx);
  88.     lib_output_polypatch(3, vert, norm);
  89.     COPY_COORD3(vert[1], vert[2]);
  90.     COPY_COORD3(norm[1], norm[2]);
  91.     lib_transform_vector(vert[2], start_radius[0], mx);
  92.     ADD2_COORD3(vert[2], base_pt);
  93.     lib_output_polypatch(3, vert, norm);
  94.  
  95.     COPY_COORD3(vert[0], vert[2]);
  96.     COPY_COORD3(norm[0], norm[2]);
  97.  
  98.     PLATFORM_MULTITASK();
  99.     }
  100. }
  101.  
  102. /*-----------------------------------------------------------------*/
  103. static void
  104. disc_evaluator(trans, theta, v, r, vert)
  105.     MATRIX trans;
  106.     double theta, v, r;
  107.     COORD3 vert;
  108. {
  109.     COORD3 tvert;
  110.  
  111.     /* Compute the position of the point */
  112.     SET_COORD3(tvert, (r + v) * cos(theta), (r + v) * sin(theta), 0.0);
  113.     lib_transform_vector(vert, tvert, trans);
  114. }
  115.  
  116. /*-----------------------------------------------------------------*/
  117. void
  118. lib_output_polygon_disc(center, normal, iradius, oradius)
  119.     COORD3 center, normal;
  120.     double iradius, oradius;
  121. {
  122.     double u, v, delta_u, delta_v;
  123.     MATRIX mx, imx;
  124.     int i, j;
  125.     COORD3 norm, vert[4];
  126.  
  127.     COPY_COORD3(norm, normal);
  128.     if ( lib_normalize_vector(norm) < EPSILON2) {
  129.     fprintf(stderr, "Bad disc normal\n");
  130.     exit(1);
  131.     }
  132.     lib_create_canonical_matrix(mx, imx, center, norm);
  133.     delta_u = 2.0 * PI / (double)(4 * gU_resolution);
  134.     delta_v = (oradius - iradius) / (double)(gV_resolution);
  135.  
  136.     /* Dump out polygons */
  137.     for (i=0,u=0.0;i<4*gU_resolution;i++,u+=delta_u) {
  138.     PLATFORM_MULTITASK();
  139.     for (j=0,v=0.0;j<gV_resolution;j++,v+=delta_v) {
  140.         disc_evaluator(imx, u, v, iradius, vert[0]);
  141.         disc_evaluator(imx, u+delta_u, v, iradius, vert[1]);
  142.         disc_evaluator(imx, u+delta_u, v+delta_v, iradius, vert[2]);
  143.         lib_output_polygon(3, vert);
  144.         COPY_COORD3(vert[1], vert[2]);
  145.         disc_evaluator(imx, u, v+delta_v, iradius, vert[2]);
  146.         lib_output_polygon(3, vert);
  147.     }
  148.     }
  149. }
  150.  
  151. /*-----------------------------------------------------------------*/
  152. void
  153. lib_output_polygon_sphere(center_pt)
  154.     COORD4 center_pt;
  155. {
  156.     double  angle;
  157.     COORD3  edge_norm[3], edge_pt[3];
  158.     long    num_face, num_edge, num_tri, num_vert;
  159.     COORD3  *x_axis, *y_axis, **pt;
  160.     COORD3  mid_axis;
  161.     MATRIX  rot_mx;
  162.     long    u_pol, v_pol;
  163.  
  164.     /* Allocate storage for the polygon vertices */
  165.     x_axis = (COORD3 *)malloc((gU_resolution+1) * sizeof(COORD3));
  166.     y_axis = (COORD3 *)malloc((gV_resolution+1) * sizeof(COORD3));
  167.     pt     = (COORD3 **)malloc((gU_resolution+1) * sizeof(COORD3 *));
  168.     if (x_axis == NULL || y_axis == NULL || pt == NULL) {
  169.     fprintf(stderr, "Failed to allocate polygon data\n");
  170.     exit(1);
  171.     }
  172.  
  173.     for (num_edge=0;num_edge<gU_resolution+1;num_edge++) {
  174.     pt[num_edge] = (COORD3 *)malloc((gV_resolution+1) * sizeof(COORD3));
  175.     if (pt[num_edge] == NULL) {
  176.         fprintf(stderr, "Failed to allocate polygon data\n");
  177.         exit(1);
  178.     }
  179.     }
  180.  
  181.     /* calculate axes used to find grid points */
  182.     for (num_edge=0;num_edge<=gU_resolution;++num_edge) {
  183.     angle = (PI/4.0) * (2.0*(double)num_edge/gU_resolution - 1.0);
  184.     mid_axis[X] = 1.0; mid_axis[Y] = 0.0; mid_axis[Z] = 0.0;
  185.     lib_create_rotate_matrix(rot_mx, Y_AXIS, angle);
  186.     lib_transform_vector(x_axis[num_edge], mid_axis, rot_mx);
  187.     }
  188.  
  189.     for (num_edge=0;num_edge<=gV_resolution;++num_edge) {
  190.     angle = (PI/4.0) * (2.0*(double)num_edge/gV_resolution - 1.0);
  191.     mid_axis[X] = 0.0; mid_axis[Y] = 1.0; mid_axis[Z] = 0.0;
  192.     lib_create_rotate_matrix(rot_mx, X_AXIS, angle);
  193.     lib_transform_vector(y_axis[num_edge], mid_axis, rot_mx);
  194.     }
  195.  
  196.     /* set up grid of points on +Z sphere surface */
  197.     for (u_pol=0;u_pol<=gU_resolution;++u_pol) {
  198.     for (v_pol=0;v_pol<=gU_resolution;++v_pol) {
  199.         CROSS(pt[u_pol][v_pol], x_axis[u_pol], y_axis[v_pol]);
  200.         lib_normalize_vector(pt[u_pol][v_pol]);
  201.     }
  202.     }
  203.  
  204.     for (num_face=0;num_face<6;++num_face) {
  205.     /* transform points to cube face */
  206.     for (u_pol=0;u_pol<=gU_resolution;++u_pol) {
  207.         for (v_pol=0;v_pol<=gV_resolution;++v_pol) {
  208.         lib_rotate_cube_face(pt[u_pol][v_pol], Z_AXIS, num_face);
  209.         }
  210.     }
  211.  
  212.     /* output grid */
  213.     for (u_pol=0;u_pol<gU_resolution;++u_pol) {
  214.         for (v_pol=0;v_pol<gV_resolution;++v_pol) {
  215.         PLATFORM_MULTITASK();
  216.         for (num_tri=0;num_tri<2;++num_tri) {
  217.             for (num_edge=0;num_edge<3;++num_edge) {
  218.             num_vert = (num_tri*2 + num_edge) % 4;
  219.             if (num_vert == 0) {
  220.                 COPY_COORD3(edge_pt[num_edge], pt[u_pol][v_pol]);
  221.             } else if ( num_vert == 1 ) {
  222.                 COPY_COORD3(edge_pt[num_edge], pt[u_pol][v_pol+1]);
  223.             } else if ( num_vert == 2 ) {
  224.                 COPY_COORD3(edge_pt[num_edge],pt[u_pol+1][v_pol+1]);
  225.             } else {
  226.                 COPY_COORD3(edge_pt[num_edge], pt[u_pol+1][v_pol]);
  227.             }
  228.             COPY_COORD3(edge_norm[num_edge], edge_pt[num_edge]);
  229.             edge_pt[num_edge][X] =
  230.                 edge_pt[num_edge][X] * center_pt[W] +
  231.                            center_pt[X];
  232.             edge_pt[num_edge][Y] =
  233.                 edge_pt[num_edge][Y] * center_pt[W] +
  234.                            center_pt[Y];
  235.             edge_pt[num_edge][Z] =
  236.                 edge_pt[num_edge][Z] * center_pt[W] +
  237.                            center_pt[Z];
  238.  
  239.             }
  240.             lib_output_polypatch(3, edge_pt, edge_norm);
  241.         }
  242.         }
  243.     }
  244.     }
  245.  
  246.     /* Release any memory used */
  247.     for (num_edge=0;num_edge<gU_resolution+1;num_edge++)
  248.     free(pt[num_edge]);
  249.     free(pt);
  250.     free(y_axis);
  251.     free(x_axis);
  252. }
  253.  
  254.  
  255. /*-----------------------------------------------------------------*/
  256. void
  257. lib_output_polygon_height(height, width, data, x0, x1, y0, y1, z0, z1)
  258.     unsigned int height, width;
  259.     float **data;
  260.     double x0, x1, y0, y1, z0, z1;
  261. {
  262.     unsigned int i, j;
  263.     double xdelta, zdelta;
  264.     COORD3 verts[3];
  265.  
  266. #if defined (applec)
  267. #pragma unused (y1)
  268. #endif /* applec */
  269.  
  270.     xdelta = (x1 - x0) / (double)(width - 1);
  271.     zdelta = (z1 - z0) / (double)(height - 1);
  272.     for (i=0;i<height-1;i++) {
  273.     for (j=0;j<width-1;j++) {
  274.         PLATFORM_MULTITASK();
  275.         SET_COORD3(verts[0], x0 + j * xdelta, y0 + data[i][j],
  276.                z0 + i * zdelta);
  277.         SET_COORD3(verts[1], x0 + (j+1) * xdelta, y0 + data[i][j+1],
  278.                z0 + i * zdelta);
  279.         SET_COORD3(verts[2], x0 + (j+1) * xdelta, y0 + data[i+1][j+1],
  280.                z0 + (i + 1) * zdelta);
  281.         lib_output_polygon(3, verts);
  282.         COPY_COORD3(verts[1], verts[2]);
  283.         SET_COORD3(verts[2], x0 + j * xdelta, y0 + data[i+1][j],
  284.                z0 + (i + 1) * zdelta);
  285.         lib_output_polygon(3, verts);
  286.     }
  287.     }
  288. }
  289.  
  290. /*-----------------------------------------------------------------*/
  291. static void
  292. torus_evaluator(trans, theta, phi, r0, r1, vert, norm)
  293.     MATRIX trans;
  294.     double theta, phi, r0, r1;
  295.     COORD3 vert, norm;
  296. {
  297.     COORD3 v0, v1, tvert, tnorm;
  298.  
  299.     /* Compute the position of the point */
  300.     SET_COORD3(tvert, (r0 + r1 * sin(theta)) * cos(phi),
  301.               (r0 + r1 * sin(theta)) * sin(phi),
  302.               r1 * cos(theta));
  303.     /* Compute the normal at that point */
  304.     SET_COORD3(v0, r1*cos(theta)*cos(phi),
  305.            r1*cos(theta)*sin(phi),
  306.           -r1*sin(theta));
  307.     SET_COORD3(v1,-(r0+r1*sin(theta))*sin(phi),
  308.            (r0+r1*sin(theta))*cos(phi),
  309.            0.0);
  310.     CROSS(tnorm, v0, v1);
  311.     lib_normalize_vector(tnorm);
  312.     lib_transform_point(vert, tvert, trans);
  313.     lib_transform_vector(norm, tnorm, trans);
  314. }
  315.  
  316. /*-----------------------------------------------------------------*/
  317. void
  318. lib_output_polygon_torus(center, normal, iradius, oradius)
  319.     COORD3 center, normal;
  320.     double iradius, oradius;
  321. {
  322.     double u, v, delta_u, delta_v;
  323.     MATRIX mx, imx;
  324.     int i, j;
  325.     COORD3 vert[4], norm[4];
  326.  
  327.     if ( lib_normalize_vector(normal) < EPSILON2) {
  328.     fprintf(stderr, "Bad torus normal\n");
  329.     exit(1);
  330.     }
  331.     lib_create_canonical_matrix(mx, imx, center, normal);
  332.     delta_u = 2.0 * PI / (double)gU_resolution;
  333.     delta_v = 2.0 * PI / (double)gV_resolution;
  334.  
  335.     /* Dump out polygons */
  336.     for (i=0,u=0.0;i<gU_resolution;i++,u+=delta_u) {
  337.     PLATFORM_MULTITASK();
  338.     for (j=0,v=0.0;j<gV_resolution;j++,v+=delta_v) {
  339.         torus_evaluator(imx, u, v, iradius, oradius, vert[0], norm[0]);
  340.         torus_evaluator(imx, u, v+delta_v, iradius, oradius,
  341.             vert[1], norm[1]);
  342.         torus_evaluator(imx, u+delta_u, v+delta_v,
  343.             iradius, oradius, vert[2], norm[2]);
  344.         lib_output_polypatch(3, vert, norm);
  345.         COPY_COORD3(vert[1], vert[2]);
  346.         COPY_COORD3(norm[1], norm[2]);
  347.         torus_evaluator(imx, u+delta_u, v, iradius, oradius,
  348.             vert[2], norm[2]);
  349.         lib_output_polypatch(3, vert, norm);
  350.     }
  351.     }
  352. }
  353. /*-----------------------------------------------------------------*/
  354. /* Generate a box as a set of 4-sided polygons */
  355. void
  356. lib_output_polygon_box(p1, p2)
  357.     COORD3 p1, p2;
  358. {
  359.     COORD3 box_verts[4];
  360.  
  361.     /* Sides */
  362.     SET_COORD3(box_verts[0], p1[X], p1[Y], p1[Z]);
  363.     SET_COORD3(box_verts[1], p1[X], p2[Y], p1[Z]);
  364.     SET_COORD3(box_verts[2], p1[X], p2[Y], p2[Z]);
  365.     SET_COORD3(box_verts[3], p1[X], p1[Y], p2[Z]);
  366.     lib_output_polygon(4, box_verts);
  367.     SET_COORD3(box_verts[3], p2[X], p1[Y], p1[Z]);
  368.     SET_COORD3(box_verts[2], p2[X], p2[Y], p1[Z]);
  369.     SET_COORD3(box_verts[1], p2[X], p2[Y], p2[Z]);
  370.     SET_COORD3(box_verts[0], p2[X], p1[Y], p2[Z]);
  371.     lib_output_polygon(4, box_verts);
  372.  
  373.     /* Front/Back */
  374.     SET_COORD3(box_verts[0], p1[X], p1[Y], p1[Z]);
  375.     SET_COORD3(box_verts[1], p1[X], p2[Y], p1[Z]);
  376.     SET_COORD3(box_verts[2], p2[X], p2[Y], p1[Z]);
  377.     SET_COORD3(box_verts[3], p2[X], p1[Y], p1[Z]);
  378.     lib_output_polygon(4, box_verts);
  379.     SET_COORD3(box_verts[3], p1[X], p1[Y], p2[Z]);
  380.     SET_COORD3(box_verts[2], p1[X], p2[Y], p2[Z]);
  381.     SET_COORD3(box_verts[1], p2[X], p2[Y], p2[Z]);
  382.     SET_COORD3(box_verts[0], p2[X], p1[Y], p2[Z]);
  383.     lib_output_polygon(4, box_verts);
  384.  
  385.     /* Top/Bottom */
  386.     SET_COORD3(box_verts[0], p1[X], p1[Y], p1[Z]);
  387.     SET_COORD3(box_verts[1], p1[X], p1[Y], p2[Z]);
  388.     SET_COORD3(box_verts[2], p2[X], p1[Y], p2[Z]);
  389.     SET_COORD3(box_verts[3], p2[X], p1[Y], p1[Z]);
  390.     lib_output_polygon(4, box_verts);
  391.     SET_COORD3(box_verts[3], p1[X], p2[Y], p1[Z]);
  392.     SET_COORD3(box_verts[2], p1[X], p2[Y], p2[Z]);
  393.     SET_COORD3(box_verts[1], p2[X], p2[Y], p2[Z]);
  394.     SET_COORD3(box_verts[0], p2[X], p2[Y], p1[Z]);
  395.     lib_output_polygon(4, box_verts);
  396. }
  397.  
  398.  
  399. /*-----------------------------------------------------------------*/
  400. /* Given a polygon defined by vertices in verts, determine which of the
  401.    components of the vertex correspond to useful x and y coordinates - with
  402.    these we can pretend the polygon is 2D to do our work on it. */
  403. static void
  404. find_axes(verts)
  405.     COORD3 *verts;
  406. {
  407.     double P1[3], P2[3], x, y, z;
  408.  
  409.     P1[0] = VERT(1, 0) - VERT(0, 0);
  410.     P1[1] = VERT(1, 1) - VERT(0, 1);
  411.     P1[2] = VERT(1, 2) - VERT(0, 2);
  412.  
  413.     P2[0] = VERT(2, 0) - VERT(0, 0);
  414.     P2[1] = VERT(2, 1) - VERT(0, 1);
  415.     P2[2] = VERT(2, 2) - VERT(0, 2);
  416.  
  417.     /* Cross product - don't need to normalize cause we're only interested
  418.       in the size of the components */
  419.     x = fabs(P1[1] * P2[2] - P1[2] * P2[1]);
  420.     y = fabs(P1[2] * P2[0] - P1[0] * P2[2]);
  421.     z = fabs(P1[0] * P2[1] - P1[1] * P2[0]);
  422.  
  423.     if (x > y && x > z) {
  424.     gPoly_Axis1 = 1;
  425.     gPoly_Axis2 = 2;
  426.     } else if (y > x && y > z) {
  427.     gPoly_Axis1 = 0;
  428.     gPoly_Axis2 = 2;
  429.     } else {
  430.     gPoly_Axis1 = 0;
  431.     gPoly_Axis2 = 1;
  432.     }
  433. }
  434.  
  435. /*-----------------------------------------------------------------*/
  436. /* Find the left most vertex in the polygon that has vertices m ... n. */
  437. static unsigned int
  438. leftmost_vertex(m, n, verts)
  439.     unsigned int m, n;
  440.     COORD3 *verts;
  441. {
  442.     unsigned int l, i;
  443.     double x;
  444.  
  445.     /* Assume the first vertex is the farthest to the left */
  446.     l = m;
  447.     x = VERT(m, gPoly_Axis1);
  448.  
  449.     /* Now see if any of the others are farther to the left */
  450.     for (i=m+1;i<=n;i++) {
  451.        if (VERT(i, gPoly_Axis1) < x) {
  452.        l = i;
  453.        x = VERT(i, gPoly_Axis1);
  454.        }
  455.     }
  456.     return l;
  457. }
  458.  
  459. /*-----------------------------------------------------------------*/
  460. /* Given the leftmost vertex in a polygon, this routine finds another vertex
  461.    can be used to safely split the polygon. */
  462. static unsigned int
  463. split_vertex(l, la, lb, m, n, verts)
  464.     unsigned int l, la, lb, m, n;
  465.     COORD3 *verts;
  466. {
  467.     unsigned int t, k, lpu, lpl;
  468.     double yu, yl;
  469.  
  470.     yu = MAX(VERT(l, gPoly_Axis2), MAX(VERT(la, gPoly_Axis2), VERT(lb, gPoly_Axis2)));
  471.     yl = MIN(VERT(l, gPoly_Axis2), MIN(VERT(la, gPoly_Axis2), VERT(lb, gPoly_Axis2)));
  472.     if (VERT(lb, gPoly_Axis2) > VERT(la, gPoly_Axis2)) {
  473.     lpu = lb;
  474.     lpl = la;
  475.     } else {
  476.     lpu = la;
  477.     lpl = lb;
  478.     }
  479.     t = (VERT(lb, gPoly_Axis1) > VERT(la, gPoly_Axis1) ? lb : la);
  480.     for (k=m;k<n;k++) {
  481.     if (k != la && k != l && k != lb) {
  482.         if (VERT(k, gPoly_Axis2) <= yu && VERT(k, gPoly_Axis2) >= yl) {
  483.         if (VERT(k, gPoly_Axis1) < VERT(t, gPoly_Axis1) &&
  484.             ((VERT(k, gPoly_Axis2) - VERT(l, gPoly_Axis2)) *
  485.              (VERT(lpu, gPoly_Axis1) - VERT(l, gPoly_Axis1))) <=
  486.             ((VERT(lpu, gPoly_Axis2) - VERT(l, gPoly_Axis2)) *
  487.              (VERT(k, gPoly_Axis1) - VERT(l, gPoly_Axis1)))) {
  488.             if (((VERT(k, gPoly_Axis2) - VERT(l, gPoly_Axis2)) *
  489.               (VERT(lpl, gPoly_Axis1) - VERT(l, gPoly_Axis1))) >=
  490.              ((VERT(lpl, gPoly_Axis2) - VERT(l, gPoly_Axis2)) *
  491.              (VERT(k, gPoly_Axis1) - VERT(l, gPoly_Axis1)))) {
  492.             t = k;
  493.             }
  494.         }
  495.         }
  496.     }
  497.     }
  498.     return t;
  499. }
  500.  
  501. /*-----------------------------------------------------------------*/
  502. /* Test polygon vertices to see if they are linear */
  503. static int
  504. linear_vertices(m, n, verts)
  505.     unsigned int m, n;
  506.     COORD3 *verts;
  507. {
  508. #if defined (applec)
  509. #pragma unused (m,n,verts)
  510. #endif /* applec */
  511.     /* Not doing anything right now */
  512.     return 0;
  513. }
  514.  
  515. /*-----------------------------------------------------------------*/
  516. /* Shift vertex indices around to make two polygons out of one. */
  517. static void
  518. perform_split(m, m1, n, n1)
  519.     int n, n1, m, m1;
  520. {
  521.     int i, j, k;
  522.  
  523.     k = n + 3 - m;
  524.     /* Move the new polygon up over the place the current one sits */
  525.     for (j=m1;j<=n1;j++) gPoly_vbuffer[j+k] = gPoly_vbuffer[j];
  526.  
  527.     /* Move top part of remaining polygon */
  528.     for (j=n;j>=n1;j--) gPoly_vbuffer[j+2] = gPoly_vbuffer[j];
  529.  
  530.     /* Move bottom part of remaining polygon */
  531.     k = n1 - m1 + 1;
  532.     for (j=m1;j>=m;j--) gPoly_vbuffer[j+k] = gPoly_vbuffer[j];
  533.  
  534.     /* Copy the new polygon so that it sits before the remaining polygon */
  535.     i = n + 3 - m;
  536.     k = m - m1;
  537.     for (j=m1;j<=n1;j++) gPoly_vbuffer[j+k] = gPoly_vbuffer[j+i];
  538. }
  539.  
  540. /*-----------------------------------------------------------------*/
  541. /* Copy an indirectly referenced triangle into the output triangle buffer */
  542. static void
  543. add_new_triangle(m, verts, norms, out_cnt, out_verts, out_norms)
  544.     unsigned int m, *out_cnt;
  545.     COORD3 *verts, *norms, **out_verts, **out_norms;
  546. {
  547.     if (out_verts != NULL) {
  548.     COPY_COORD3(out_verts[*out_cnt][0], verts[gPoly_vbuffer[m]]);
  549.     COPY_COORD3(out_verts[*out_cnt][1], verts[gPoly_vbuffer[m+1]]);
  550.     COPY_COORD3(out_verts[*out_cnt][2], verts[gPoly_vbuffer[m+2]]);
  551.     }
  552.     if (out_norms != NULL) {
  553.     COPY_COORD3(out_norms[*out_cnt][0], norms[gPoly_vbuffer[m]]);
  554.     COPY_COORD3(out_norms[*out_cnt][1], norms[gPoly_vbuffer[m+1]]);
  555.     COPY_COORD3(out_norms[*out_cnt][2], norms[gPoly_vbuffer[m+2]]);
  556.     }
  557.     *out_cnt += 1;
  558. }
  559.  
  560. /*-----------------------------------------------------------------*/
  561. static void
  562. split_buffered_polygon(cnt, verts, norms, out_cnt, out_verts, out_norms)
  563.     unsigned int cnt, *out_cnt;
  564.     COORD3 *verts, *norms, **out_verts, **out_norms;
  565. {
  566.     unsigned int i, m, m1, n, n1;
  567.     unsigned int l, la, lb, ls;
  568.  
  569.     /* No triangles to start with */
  570.     *out_cnt = 0;
  571.  
  572.     /* Initialize the polygon splitter */
  573.     gPoly_end[0] = -1;
  574.     gPoly_end[1] = cnt-1;
  575.  
  576.     /* Split and push polygons until they turn into triangles */
  577.     for (i=1;i>0;) {
  578.     m = gPoly_end[i-1] + 1;
  579.     n = gPoly_end[i];
  580.     if (n - m == 2) {
  581.         if (!linear_vertices(m, n, verts)) {
  582.         add_new_triangle(m, verts, norms, out_cnt,
  583.             out_verts, out_norms);
  584.         }
  585.         i = i - 1;
  586.     } else {
  587.         l = leftmost_vertex(m, n, verts);
  588.         la = (l == n ? m : l + 1);
  589.         lb = (l == m ? n : l - 1);
  590.         ls = split_vertex(l, la, lb, m, n, verts);
  591.         if (ls == la || ls == lb) {
  592.         m1 = (la < lb ? la : lb);
  593.         n1 = (la > lb ? la : lb);
  594.         } else {
  595.         m1 = (l < ls ? l : ls);
  596.         n1 = (l > ls ? l : ls);
  597.         }
  598.         perform_split(m, m1, n, n1);
  599.         gPoly_end[i++] = m + n1 - m1;
  600.         gPoly_end[i] = n + 2;
  601.     }
  602.     }
  603. }
  604.  
  605. /*-----------------------------------------------------------------*/
  606. /*
  607.  * Split an arbitrary polygon into triangles.
  608.  */
  609. static void
  610. split_polygon(n, vert, norm)
  611.     unsigned int n;
  612.     COORD3 *vert, *norm;
  613. {
  614.     COORD4 tvert[3], v0, v1;
  615.     COORD3 **out_verts, **out_norms;
  616.     int i, ii, j ;
  617.     unsigned int t, out_n;
  618.     object_ptr new_object;
  619.  
  620.     /* Can't split a NULL vertex list */
  621.     if (vert == NULL) return;
  622.     if (gPoly_vbuffer == NULL) { /* [esp] Added error */
  623.     lib_storage_initialize();
  624.     /* [are] removed error, go and initialize if it hasn't been done. */
  625.     }
  626.  
  627.     /* Allocate space to hold the intermediate polygon stacks */
  628.     out_verts = (COORD3 **)malloc((n - 2) * sizeof(COORD3 *));
  629.     if (norm != NULL)
  630.     out_norms = (COORD3 **)malloc((n - 2) * sizeof(COORD3 *));
  631.     else
  632.     out_norms = NULL;
  633.     for (i=0;i<n-2;i++) {
  634.     out_verts[i] = (COORD3 *)malloc(3 * sizeof(COORD3));
  635.     if (norm != NULL)
  636.         out_norms[i] = (COORD3 *)malloc(3 * sizeof(COORD3));
  637.     }
  638.  
  639.     /* Start with a strict identity of vertices in verts and vertices in
  640.        the polygon buffer */
  641.     for (i=0;i<n;i++) gPoly_vbuffer[i] = i;
  642.  
  643.     /* Make sure we know which axes to look at */
  644.     find_axes(vert);
  645.  
  646.     out_n = 0;
  647.     split_buffered_polygon(n, vert, norm, &out_n, out_verts, out_norms);
  648.  
  649.     /* Now output the triangles that we generated */
  650.     for (t=0;t<out_n;t++) {
  651.     PLATFORM_MULTITASK();
  652.     if (gRT_out_format == OUTPUT_DELAYED ||
  653.         gRT_out_format == OUTPUT_PLG) {
  654.         /* Save all the pertinent information */
  655.         new_object = (object_ptr)malloc(sizeof(struct object_struct));
  656.         if (new_object == NULL) return;
  657.         if (norm == NULL) {
  658.         new_object->object_type  = POLYGON_OBJ;
  659.         new_object->object_data.polygon.tot_vert = 3;
  660.         new_object->object_data.polygon.vert =
  661.             (COORD3 *)malloc(3 * sizeof(COORD3));
  662.         if (new_object->object_data.polygon.vert == NULL) return;
  663.         } else {
  664.         new_object->object_type  = POLYPATCH_OBJ;
  665.         new_object->object_data.polypatch.tot_vert = 3;
  666.         new_object->object_data.polypatch.vert =
  667.             (COORD3 *)malloc(3 * sizeof(COORD3));
  668.         if (new_object->object_data.polypatch.vert == NULL) return;
  669.         new_object->object_data.polypatch.norm =
  670.             (COORD3 *)malloc(3 * sizeof(COORD3));
  671.         if (new_object->object_data.polypatch.norm == NULL) return;
  672.         }
  673.         new_object->curve_format = OUTPUT_PATCHES;
  674.         new_object->surf_index   = gTexture_count;
  675.         for (i=0;i<3;i++) {
  676.         if (norm == NULL)
  677.             COPY_COORD3(new_object->object_data.polygon.vert[i],
  678.                 out_verts[t][i])
  679.         else {
  680.             COPY_COORD3(new_object->object_data.polypatch.vert[i],
  681.                 out_verts[t][i])
  682.             COPY_COORD3(new_object->object_data.polypatch.norm[i],
  683.                 out_norms[t][i])
  684.         }
  685.         }
  686.        if (gRT_out_format == OUTPUT_PLG) {
  687.            /* We are currently in the process of turning objects
  688.           into a stack of polygons.  Since we don't want to
  689.           put these polygons back onto the original stack of
  690.           objects, we put them into gPolygon_stack */
  691.            new_object->next_object = gPolygon_stack;
  692.            gPolygon_stack = new_object;
  693.         }
  694.        else {
  695.            new_object->next_object = gLib_objects;
  696.            gLib_objects = new_object;
  697.        }
  698.     } else {
  699.         switch (gRT_out_format) {
  700.         case OUTPUT_VIDEO:
  701.             /* First make sure the display has been opened for
  702.              * drawing
  703.              */
  704.             if (!gView_init_flag) {
  705.             lib_create_view_matrix(gViewpoint.tx, gViewpoint.from, gViewpoint.at,
  706.                            gViewpoint.up, gViewpoint.resx, gViewpoint.resy,
  707.                            gViewpoint.angle, gViewpoint.aspect);
  708.             display_init(gViewpoint.resx, gViewpoint.resy, gBkgnd_color);
  709.             gView_init_flag = 1;
  710.             }
  711.             /* Step through each segment of the polygon, projecting it
  712.                onto the screen. */
  713.             for (i=0;i<3;i++) {
  714.             COPY_COORD3(tvert[0], out_verts[t][i]);
  715.             tvert[0][W] = 1.0;
  716.             lib_transform_coord(v0, tvert[0], gViewpoint.tx);
  717.             COPY_COORD3(tvert[1], out_verts[t][(i+1)%3]);
  718.             tvert[1][W] = 1.0;
  719.             lib_transform_coord(v1, tvert[1], gViewpoint.tx);
  720.             /* Do the perspective transform on the points */
  721.             v0[X] /= v0[W]; v0[Y] /= v0[W];
  722.             v1[X] /= v1[W]; v1[Y] /= v1[W];
  723.             if (lib_clip_to_box(v0, v1, gView_bounds))
  724.                 display_line((int)v0[X], (int)v0[Y],
  725.                     (int)v1[X], (int)v1[Y], gFgnd_color);
  726.             }
  727.             break;
  728.  
  729.         case OUTPUT_NFF:
  730.             if (norm == NULL) {
  731.             fprintf(gOutfile, "p 3\n");
  732.             for (i=0;i<3;++i) {
  733.                 fprintf(gOutfile, "%g %g %g\n",
  734.                     out_verts[t][i][X], out_verts[t][i][Y],
  735.                     out_verts[t][i][Z]);
  736.             }
  737.             } else {
  738.             fprintf(gOutfile, "pp 3\n");
  739.             for (i=0;i<3;++i) {
  740.                 fprintf(gOutfile, "%g %g %g %g %g %g\n",
  741.                     out_verts[t][i][X], out_verts[t][i][Y],
  742.                     out_verts[t][i][Z], out_norms[t][i][X],
  743.                     out_norms[t][i][Y], out_norms[t][i][Z]);
  744.             }
  745.             }
  746.            break;
  747.  
  748.         case OUTPUT_POVRAY_10:
  749.         case OUTPUT_POVRAY_20:
  750.             tab_indent();
  751.             fprintf(gOutfile, "object {\n");
  752.             tab_inc();
  753.  
  754.             tab_indent();
  755.             if (norm == NULL)
  756.             fprintf(gOutfile, "triangle {\n");
  757.             else
  758.             fprintf(gOutfile, "smooth_triangle {\n");
  759.             tab_inc();
  760.  
  761.             for (i=0;i<3;++i) {
  762.             tab_indent();
  763.             if (gRT_out_format == OUTPUT_POVRAY_10) {
  764.                 fprintf(gOutfile, "<%g %g %g>",
  765.                    out_verts[t][i][X],
  766.                    out_verts[t][i][Y],
  767.                    out_verts[t][i][Z]);
  768.                 if (norm != NULL)
  769.                 fprintf(gOutfile, " <%g %g %g>",
  770.                        out_norms[t][i][X],
  771.                        out_norms[t][i][Y],
  772.                        out_norms[t][i][Z]);
  773.             } else {
  774.                 fprintf(gOutfile, "<%g, %g, %g>",
  775.                    out_verts[t][i][X],
  776.                    out_verts[t][i][Y],
  777.                    out_verts[t][i][Z]);
  778.                 if (norm != NULL)
  779.                    fprintf(gOutfile, " <%g, %g, %g>",
  780.                       out_norms[t][i][X],
  781.                       out_norms[t][i][Y],
  782.                       out_norms[t][i][Z]);
  783.                 if (i < 2)
  784.                    fprintf(gOutfile, ",");
  785.             }
  786.             fprintf(gOutfile, "\n");
  787.             } /*for*/
  788.  
  789.             tab_dec();
  790.             tab_indent();
  791.             fprintf(gOutfile, "} // tri\n");
  792.  
  793.             if (gTexture_name != NULL) {
  794.                tab_indent();
  795.                fprintf(gOutfile, "texture { %s }\n", gTexture_name);
  796.             }
  797.  
  798.             tab_dec();
  799.             tab_indent();
  800.             fprintf(gOutfile, "} // object\n");
  801.  
  802.             fprintf(gOutfile, "\n");
  803.             break;
  804.  
  805.         case OUTPUT_POLYRAY:
  806.             if (norm == NULL) {
  807.             tab_indent();
  808.             fprintf(gOutfile, "object { polygon 3,");
  809.             for (i=0;i<3;i++) {
  810.                 fprintf(gOutfile, " <%g, %g, %g>",
  811.                     out_verts[t][i][X], out_verts[t][i][Y],
  812.                     out_verts[t][i][Z]);
  813.                 if (i < 2)
  814.                 fprintf(gOutfile, ", ");
  815.             }
  816.             } else {
  817.             tab_indent();
  818.             fprintf(gOutfile, "object { patch ");
  819.             for (i=0;i<3;i++) {
  820.                 fprintf(gOutfile, " <%g, %g, %g>, <%g, %g, %g>",
  821.                     out_verts[t][i][X], out_verts[t][i][Y],
  822.                     out_verts[t][i][Z], out_norms[t][i][X],
  823.                     out_verts[t][i][Y], out_norms[t][i][Z]);
  824.                 if (i < 2)
  825.                 fprintf(gOutfile, ", ");
  826.             }
  827.             }
  828.             if (gTexture_name != NULL)
  829.             fprintf(gOutfile, " %s", gTexture_name);
  830.             fprintf(gOutfile, " }\n");
  831.             fprintf(gOutfile, "\n");
  832.             break;
  833.  
  834.         case OUTPUT_VIVID:
  835.             if (norm == NULL) {
  836.             tab_indent();
  837.             fprintf(gOutfile, "polygon { points 3 ");
  838.             for (i=0;i<3;i++) {
  839.                 fprintf(gOutfile, " vertex %g %g %g ",
  840.                     out_verts[t][i][X], out_verts[t][i][Y],
  841.                     out_verts[t][i][Z]);
  842.             }
  843.             } else {
  844.             fprintf(gOutfile, "patch {");
  845.             for (i=0;i<3;++i) {
  846.                 fprintf(gOutfile,
  847.                     " vertex %g %g %g  normal %g %g %g ",
  848.                     out_verts[t][i][X], out_verts[t][i][Y],
  849.                     out_verts[t][i][Z], out_norms[t][i][X],
  850.                     out_norms[t][i][Y], out_norms[t][i][Z]);
  851.             }
  852.             }
  853.             fprintf(gOutfile, " }\n");
  854.             fprintf(gOutfile, "\n");
  855.             break;
  856.  
  857.         case OUTPUT_QRT:
  858.             /* Doesn't matter if there are vertex normals,
  859.              * QRT can't use them.
  860.              */
  861.             fprintf(gOutfile, "TRIANGLE ( ");
  862.             fprintf(gOutfile, "loc = (%g, %g, %g), ",
  863.                   out_verts[t][0][X], out_verts[t][0][Y],
  864.                   out_verts[t][0][Z]);
  865.             fprintf(gOutfile, "vect1 = (%g, %g, %g), ",
  866.                   out_verts[t][1][X] - out_verts[t][0][X],
  867.                   out_verts[t][1][Y] - out_verts[t][0][Y],
  868.                   out_verts[t][1][Z] - out_verts[t][0][Z]);
  869.             fprintf(gOutfile, "vect2 = (%g, %g, %g) ",
  870.                   out_verts[t][2][X] - out_verts[t][0][X],
  871.                   out_verts[t][2][Y] - out_verts[t][0][Y],
  872.                   out_verts[t][2][Z] - out_verts[t][0][Z]);
  873.             fprintf(gOutfile, " );\n");
  874.             break;
  875.  
  876.         case OUTPUT_RAYSHADE:
  877.             fprintf(gOutfile, "triangle ");
  878.             if (gTexture_name != NULL)
  879.             fprintf(gOutfile, "%s ", gTexture_name);
  880.             for (i=0;i<3;i++) {
  881.             fprintf(gOutfile, "%g %g %g ",
  882.                 out_verts[t][i][X], out_verts[t][i][Y],
  883.                 out_verts[t][i][Z]);
  884.             if (norm != NULL)
  885.                 fprintf(gOutfile, "%g %g %g ",
  886.                     out_norms[t][i][X], out_norms[t][i][Y],
  887.                     out_norms[t][i][Z]);
  888.             }
  889.             fprintf(gOutfile, "\n");
  890.             break;
  891.  
  892.         case OUTPUT_ART:
  893.             tab_indent();
  894.             fprintf(gOutfile, "polygon {\n");
  895.             tab_inc();
  896.  
  897.             tab_indent();
  898.             for (i=0;i<3;i++) {
  899.             tab_indent();
  900.             fprintf(gOutfile, "vertex(%f, %f, %f)",
  901.                 out_verts[t][i][X], out_verts[t][i][Y],
  902.                 out_verts[t][i][Z]);
  903.             if (norm != NULL)
  904.                 fprintf(gOutfile, ", (%f, %f, %f)\n",
  905.                     out_norms[t][i][X], out_norms[t][i][Y],
  906.                     out_norms[t][i][Z]);
  907.             else
  908.                 fprintf(gOutfile, "\n");
  909.             }
  910.             tab_dec();
  911.             tab_indent();
  912.             fprintf(gOutfile, "}\n");
  913.             fprintf(gOutfile, "\n");
  914.             break;
  915.  
  916.         case OUTPUT_RTRACE:
  917.             if (norm == NULL) {
  918.             fprintf(gOutfile, "5 %d %g 0 0 0 1 1 1 -\n",
  919.                 gTexture_count, gTexture_ior);
  920.             fprintf(gOutfile, "3 1 2 3\n\n");
  921.             } else {
  922.             fprintf(gOutfile, "6 %d %g 0 0 0 1 1 1 -\n",
  923.                 gTexture_count, gTexture_ior);
  924.             }
  925.             for (i=0;i<3;i++) {
  926.             fprintf(gOutfile, "%g %g %g",
  927.                 out_verts[t][i][X], out_verts[t][i][Y],
  928.                 out_verts[t][i][Z]);
  929.             if (norm != NULL) {
  930.                 fprintf(gOutfile, " %g %g %g",
  931.                     out_norms[t][i][X], out_norms[t][i][Y],
  932.                     out_norms[t][i][Z]);
  933.             }
  934.             fprintf(gOutfile, "\n");
  935.             }
  936.             fprintf(gOutfile, "\n");
  937.             break;
  938.  
  939.         case OUTPUT_RAWTRI:
  940.             for (i=0;i<3;++i) {
  941.             fprintf(gOutfile, "%-10.5g %-10.5g %-10.5g  ",
  942.                 out_verts[t][i][X], out_verts[t][i][Y],
  943.                 out_verts[t][i][Z]);
  944.             }
  945.  
  946. #ifdef RAWTRI_WITH_TEXTURES
  947.             /* raw triangle format extension to do textured raw
  948.              * triangles */
  949.             if (gTexture_name != NULL)
  950.             fprintf(gOutfile, "%s", gTexture_name);
  951.             else
  952.             /* for lack of a better name */
  953.             fprintf(gOutfile, "texNone");
  954. #endif /* RAWTRI_WITH_TEXTURES */
  955.  
  956.             fprintf(gOutfile, "\n");
  957.             break;
  958.  
  959.         case OUTPUT_OBJ:
  960.             /* First the vertices */
  961.             for (i=0;i<3;++i)
  962.                fprintf(gOutfile, "v %g %g %g\n",
  963.                 out_verts[t][i][X], out_verts[t][i][Y],
  964.                 out_verts[t][i][Z]);
  965.             if (norm != NULL)
  966.             for (i=0;i<3;++i)
  967.                 fprintf(gOutfile, "vn %g %g %g\n",
  968.                     out_norms[t][i][X], out_norms[t][i][Y],
  969.                     out_norms[t][i][Z]);
  970.             /* Then the face - note that we add one to the count
  971.                since Wavefront vertices start at 1, not 0. */
  972.             if (norm == NULL) {
  973.                fprintf(gOutfile, "f %d %d %d\n",
  974.                    gVertex_count+1, gVertex_count+2,
  975.                    gVertex_count+3);
  976.                gVertex_count += 3;
  977.                }
  978.             else {
  979.                fprintf(gOutfile, "f %d//%d %d//%d %d//%d\n",
  980.                    gVertex_count+1, gNormal_count+1,
  981.                    gVertex_count+2, gNormal_count+2,
  982.                    gVertex_count+3, gNormal_count+3);
  983.                gVertex_count += 3;
  984.                gNormal_count += 3;
  985.                }
  986.             break;
  987.  
  988.         case OUTPUT_RIB:
  989.             /* The order of the vertices has to be inverted for the
  990.                LH system */
  991.             tab_indent();
  992.             fprintf(gOutfile, "Polygon \"P\" [\n");
  993.             tab_inc();
  994.             for (i=2;i>=0;i--)
  995.             {
  996.             tab_indent();
  997.             fprintf(gOutfile, "%#g %#g %#g\n",
  998.                   out_verts[t][i][X], out_verts[t][i][Y],
  999.                   out_verts[t][i][Z]);
  1000.             }
  1001.             if (norm != NULL)
  1002.             {
  1003.             tab_dec();
  1004.             tab_indent();
  1005.             tab_inc();
  1006.             fprintf(gOutfile, "]  \"N\" [\n");
  1007.             for (i=2;i>=0;i--)
  1008.             {
  1009.                 /* Normals are also inverted in LH */
  1010.                 tab_indent();
  1011.                 fprintf(gOutfile, "%#g %#g %#g\n",
  1012.                      -out_norms[t][i][X], -out_norms[t][i][Y],
  1013.                      -out_norms[t][i][Z]);
  1014.             }
  1015.             }
  1016.             tab_dec();
  1017.             tab_indent();
  1018.             fprintf(gOutfile, "]\n");
  1019.             break;
  1020.  
  1021.         case OUTPUT_DXF:
  1022.             fprintf(gOutfile, "  0\n3DFACE\n  8\n0----\n" ) ;
  1023.             for (i=0;i<4;++i) {
  1024.             ii = (i == 3) ? 2 : i ;
  1025.             for (j=0;j<3;++j) {
  1026.                 fprintf(gOutfile, " %d%d\n%0.4f\n",j+1,i,
  1027.                     out_verts[t][ii][j] ) ;
  1028.             }
  1029.             }
  1030.             break;
  1031.  
  1032.         } /* switch */
  1033.     } /* else !OUTPUT_DELAYED */
  1034.     } /* else for loop */
  1035.  
  1036.     /* Clean up intermediate storage */
  1037.     for (i=0;i<n-2;i++) {
  1038.     free(out_verts[i]);
  1039.     if (norm != NULL)
  1040.         free(out_norms[i]);
  1041.     }
  1042.  
  1043.     free(out_verts);
  1044.     if (out_norms != NULL) free(out_norms);
  1045. }
  1046.  
  1047. /*-----------------------------------------------------------------*/
  1048. /*
  1049.  * Output polygon.  A polygon is defined by a set of vertices.  With these
  1050.  * databases, a polygon is defined to have all points coplanar.  A polygon has
  1051.  * only one side, with the order of the vertices being counterclockwise as you
  1052.  * face the polygon (right-handed coordinate system).
  1053.  *
  1054.  * The output format is always:
  1055.  *     "p" total_vertices
  1056.  *     vert1.x vert1.y vert1.z
  1057.  *     [etc. for total_vertices polygons]
  1058.  *
  1059.  */
  1060. void
  1061. lib_output_polygon(tot_vert, vert)
  1062.     int tot_vert;
  1063.     COORD3 vert[];
  1064. {
  1065.     object_ptr new_object;
  1066.     int num_vert, i, j;
  1067.     COORD3 x;
  1068.     COORD4 tvert[3], v0, v1;
  1069.  
  1070.     /* First lets do a couple of checks to see if this is a valid polygon */
  1071.     for (i=0;i<tot_vert;) {
  1072.     /* If there are two adjacent coordinates that degenerate then
  1073.        collapse them down to one */
  1074.     SUB3_COORD3(x, vert[i], vert[(i+1)%tot_vert]);
  1075.     if (lib_normalize_vector(x) < EPSILON2) {
  1076.         for (j=i;j<tot_vert-1;j++)
  1077.         memcpy(&vert[j], &vert[j+1], sizeof(COORD4));
  1078.         tot_vert--;
  1079.     }
  1080.     else {
  1081.         i++;
  1082.     }
  1083.     }
  1084.  
  1085.     if (tot_vert < 3)
  1086.     /* No such thing as a poly that only has two sides */
  1087.     return;
  1088.  
  1089.     if (gRT_out_format == OUTPUT_DELAYED) {
  1090.     /* Save all the pertinent information */
  1091.     new_object = (object_ptr)malloc(sizeof(struct object_struct));
  1092.     new_object->object_data.polygon.vert =
  1093.         (COORD3 *)malloc(tot_vert * sizeof(COORD3));
  1094.     if (new_object == NULL || new_object->object_data.polygon.vert == NULL)
  1095.         /* Quietly fail */
  1096.         return;
  1097.     new_object->object_type  = POLYGON_OBJ;
  1098.     new_object->curve_format = OUTPUT_PATCHES;
  1099.     new_object->surf_index   = gTexture_count;
  1100.     new_object->object_data.polygon.tot_vert = tot_vert;
  1101.     for (i=0;i<tot_vert;i++)
  1102.         COPY_COORD3(new_object->object_data.polygon.vert[i], vert[i])
  1103.     new_object->next_object = gLib_objects;
  1104.     gLib_objects = new_object;
  1105.     } else {
  1106.     switch (gRT_out_format) {
  1107.         case OUTPUT_VIDEO:
  1108.         /* First make sure the display has been opened for drawing */
  1109.         if (!gView_init_flag) {
  1110.             lib_create_view_matrix(gViewpoint.tx, gViewpoint.from, gViewpoint.at,
  1111.                        gViewpoint.up, gViewpoint.resx, gViewpoint.resy,
  1112.                        gViewpoint.angle, gViewpoint.aspect);
  1113.             display_init(gViewpoint.resx, gViewpoint.resy, gBkgnd_color);
  1114.             gView_init_flag = 1;
  1115.         }
  1116.         /* Step through each segment of the polygon, projecting it
  1117.             onto the screen. */
  1118.         for (i=0;i<tot_vert;i++) {
  1119.             COPY_COORD3(tvert[0], vert[i]);
  1120.             tvert[0][W] = 1.0;
  1121.             lib_transform_coord(v0, tvert[0], gViewpoint.tx);
  1122.             COPY_COORD3(tvert[1], vert[(i+1)%tot_vert]);
  1123.             tvert[1][W] = 1.0;
  1124.             lib_transform_coord(v1, tvert[1], gViewpoint.tx);
  1125.             /* Do the perspective transform on the points */
  1126.             v0[X] /= v0[W]; v0[Y] /= v0[W];
  1127.             v1[X] /= v1[W]; v1[Y] /= v1[W];
  1128.             if (lib_clip_to_box(v0, v1, gView_bounds))
  1129.             display_line((int)v0[X], (int)v0[Y],
  1130.                 (int)v1[X], (int)v1[Y], gFgnd_color);
  1131.         }
  1132.         break;
  1133.  
  1134.         case OUTPUT_NFF:
  1135.         fprintf(gOutfile, "p %d\n", tot_vert);
  1136.         for (num_vert=0;num_vert<tot_vert;++num_vert)
  1137.             fprintf(gOutfile, "%g %g %g\n",
  1138.                 vert[num_vert][X],
  1139.                 vert[num_vert][Y],
  1140.                 vert[num_vert][Z]);
  1141.         break;
  1142.  
  1143.         case OUTPUT_OBJ:
  1144.         /* First the vertices */
  1145.         for (num_vert=0;num_vert<tot_vert;++num_vert)
  1146.             fprintf(gOutfile, "v %g %g %g\n",
  1147.                 vert[num_vert][X],
  1148.                 vert[num_vert][Y],
  1149.                 vert[num_vert][Z]);
  1150.         /* Then the face - note that we add one to the count
  1151.            since Wavefront vertices start at 1, not 0. */
  1152.         fprintf(gOutfile, "f ");
  1153.         for (num_vert=0;num_vert<tot_vert;num_vert++) {
  1154.            fprintf(gOutfile, "%d", gVertex_count+num_vert+1);
  1155.            if (num_vert < tot_vert - 1)
  1156.               fprintf(gOutfile, " ");
  1157.            }
  1158.         fprintf(gOutfile, "\n");
  1159.         gVertex_count += tot_vert;
  1160.         break;
  1161.  
  1162.         case OUTPUT_POVRAY_10:
  1163.         case OUTPUT_POVRAY_20:
  1164.         case OUTPUT_QRT:
  1165.         case OUTPUT_PLG:
  1166.         case OUTPUT_RAWTRI:
  1167.         case OUTPUT_DXF:
  1168.         /*
  1169.         These renderers don't do arbitrary polygons, split the polygon
  1170.         into triangles for output
  1171.         */
  1172.         split_polygon(tot_vert, vert, NULL);
  1173.         break;
  1174.  
  1175.         case OUTPUT_POLYRAY:
  1176.         tab_indent();
  1177.         fprintf(gOutfile, "object { polygon %d,", tot_vert);
  1178.         for (num_vert = 0; num_vert < tot_vert; num_vert++) {
  1179.             fprintf(gOutfile, " <%g, %g, %g>",
  1180.                  vert[num_vert][X],
  1181.                  vert[num_vert][Y],
  1182.                  vert[num_vert][Z]);
  1183.             if (num_vert < tot_vert-1)
  1184.             fprintf(gOutfile, ", ");
  1185.         }
  1186.         if (gTexture_name != NULL)
  1187.             fprintf(gOutfile, " %s", gTexture_name);
  1188.         fprintf(gOutfile, " }\n");
  1189.         fprintf(gOutfile, "\n");
  1190.         break;
  1191.  
  1192.         case OUTPUT_VIVID:
  1193.         tab_indent();
  1194.         fprintf(gOutfile, "polygon { points %d ", tot_vert);
  1195.         for (num_vert = 0; num_vert < tot_vert; num_vert++) {
  1196.             /* Vivid has problems with very long input lines, so in
  1197.              * order to handle polygons with many vertices, we split
  1198.              * the vertices one to a line.
  1199.              */
  1200.             fprintf(gOutfile, " vertex %g %g %g \n",
  1201.                  vert[num_vert][X],
  1202.                  vert[num_vert][Y],
  1203.                  vert[num_vert][Z]);
  1204.         }
  1205.         fprintf(gOutfile, " }\n");
  1206.         fprintf(gOutfile, "\n");
  1207.         break;
  1208.  
  1209.         case OUTPUT_RAYSHADE:
  1210.         fprintf(gOutfile, "polygon ");
  1211.         if (gTexture_name != NULL)
  1212.             fprintf(gOutfile, "%s ", gTexture_name);
  1213.         for (num_vert=0;num_vert<tot_vert;num_vert++) {
  1214.             if (!(num_vert%3)) fprintf(gOutfile, "\n");
  1215.             fprintf(gOutfile, "%g %g %g ",
  1216.                 vert[num_vert][X],
  1217.                 vert[num_vert][Y],
  1218.                 vert[num_vert][Z]);
  1219.         }
  1220.         fprintf(gOutfile, "\n");
  1221.         break;
  1222.  
  1223.         case OUTPUT_RTRACE:
  1224.         fprintf(gOutfile, "5 %d %g 0 0 0 1 1 1 -\n",
  1225.               gTexture_count, gTexture_ior);
  1226.         fprintf(gOutfile, "%d ", tot_vert);
  1227.         for (num_vert=0;num_vert<tot_vert;num_vert++)
  1228.             fprintf(gOutfile, "%d ", num_vert+1);
  1229.         fprintf(gOutfile, "\n\n");
  1230.         for (num_vert=0;num_vert<tot_vert;num_vert++) {
  1231.             fprintf(gOutfile, "%g %g %g\n",
  1232.                 vert[num_vert][X],
  1233.                 vert[num_vert][Y],
  1234.                 vert[num_vert][Z]);
  1235.         }
  1236.         fprintf(gOutfile, "\n");
  1237.         break;
  1238.  
  1239.         case OUTPUT_ART:
  1240.         tab_indent();
  1241.         fprintf(gOutfile, "polygon {\n");
  1242.         tab_inc();
  1243.  
  1244.         for (num_vert=0;num_vert<tot_vert;num_vert++) {
  1245.             tab_indent();
  1246.             fprintf(gOutfile, "vertex(%f, %f, %f)\n",
  1247.                   vert[num_vert][X],
  1248.                   vert[num_vert][Y],
  1249.                   vert[num_vert][Z]);
  1250.         }
  1251.         tab_dec();
  1252.         tab_indent();
  1253.         fprintf(gOutfile, "}\n");
  1254.         fprintf(gOutfile, "\n");
  1255.         break;
  1256.  
  1257.         case OUTPUT_RIB:
  1258.         tab_indent();
  1259.         fprintf(gOutfile, "Polygon \"P\" [\n");
  1260.         tab_inc();
  1261.  
  1262.         for (num_vert=tot_vert-1;num_vert>=0;num_vert--)
  1263.         {
  1264.             tab_indent();
  1265.             fprintf(gOutfile, "%#g %#g %#g\n",
  1266.                 vert[num_vert][X], vert[num_vert][Y],
  1267.                 vert[num_vert][Z]);
  1268.         }
  1269.  
  1270.         tab_dec();
  1271.         tab_indent();
  1272.         fprintf(gOutfile, "]\n");
  1273.         break;
  1274.  
  1275.      } /* switch */
  1276.     } /* else !OUTPUT_DELAYED */
  1277. }
  1278.  
  1279.  
  1280. /*-----------------------------------------------------------------*/
  1281. /*
  1282.  * Output polygonal patch.  A patch is defined by a set of vertices and their
  1283.  * normals.  With these databases, a patch is defined to have all points
  1284.  * coplanar.  A patch has only one side, with the order of the vertices being
  1285.  * counterclockwise as you face the patch (right-handed coordinate system).
  1286.  *
  1287.  * The output format is always:
  1288.  *   "pp" total_vertices
  1289.  *   vert1.x vert1.y vert1.z norm1.x norm1.y norm1.z
  1290.  *   [etc. for total_vertices polygonal patches]
  1291.  *
  1292.  */
  1293. void
  1294. lib_output_polypatch(tot_vert, vert, norm)
  1295.     int tot_vert;
  1296.     COORD3 vert[], norm[];
  1297. {
  1298.     /* None of the currently supported renderers are capable of directly
  1299.        generating polygon patches of more than 3 sides.   Therefore we
  1300.        will call a routine to split the patch into triangles.
  1301.     */
  1302.     split_polygon(tot_vert, vert, norm);
  1303. }
  1304.